package com.cloud.bc.controller.pay;

import cn.hutool.core.convert.Convert;
import com.cloud.bc.config.WXPayConfigImpl;
import com.cloud.bc.controller.BaseController;
import com.cloud.bc.model.domain.UserInfo;
import com.cloud.bc.model.entity.BcPaymenorders;
import com.cloud.bc.model.entity.BcSetmealOrders;
import com.cloud.bc.model.enums.WxPayEnum;
import com.cloud.bc.service.BcPaymenordersService;
import com.cloud.bc.service.BcSetmealOrdersService;
import com.cloud.bc.service.BcUsersService;
import com.cloud.common.util.IpUtils;
import com.cloud.wx.config.WeiXinPayConfig;
import com.cloud.wx.pay.WXPay;
import com.cloud.wx.pay.WXPayUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@AllArgsConstructor
@Controller
@RequestMapping("pay/weixin")
public class PayWeiXinController extends BaseController {
    private final BcSetmealOrdersService bcSetmealOrdersService;
    private final BcUsersService bcUsersService;
    private final BcPaymenordersService bcPaymenordersService;
    private final WeiXinPayConfig weiXinPayConfig;

    /**
     * 创建微信第三方订单
     */
    @SneakyThrows
    @GetMapping("{source}/{orderId}")
    public ModelAndView weixin(HttpServletRequest request, HttpServletResponse response,
                               @PathVariable("source") String source,
                               @PathVariable("orderId") String orderId) {
        String viewUrl = source.replace("pc", "");
        UserInfo userInfo = bcUsersService.getUserInfo(request);
        BcPaymenorders bcPaymenorders = new BcPaymenorders();
        bcPaymenorders.setUserId(userInfo.getId());
        bcPaymenorders.setOrderId(orderId);
        BcPaymenorders bcPaymenordersResult = bcPaymenordersService.selectOne(bcPaymenorders);
        if (null == bcPaymenordersResult || Convert.toInt(bcPaymenordersResult.getId(), 0) <= 0) {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write("<script>alert('系统错误，请不要篡改信息!');window.location='/" + viewUrl + "';</script>");
            return null;
        }

//        判断，如果是微信 手机端用JSAPI,电脑端用Native
        String userAgent = request.getHeader("user-agent").toLowerCase();


        String payType = WxPayEnum.NATIVE.getTitle();
        if (userAgent.contains("micromessenger")) {
//如果是微信就用jsapi
            payType = WxPayEnum.JSAPI.getTitle();
        }
        ModelAndView view = null;
        //统一下单
        String wxPrePayId = getWxPrePayId(request, bcPaymenordersResult, payType);

        if (userAgent.contains("micromessenger")) {
            //微信客户端
            view = baseView(request, "微信支付", "pc/pay/weixinjsapi");
            //TODO 创建第三方支付，跳转到第三方支付平台
            //调用微信统一下单接口
            long currentTimestamp = WXPayUtil.getCurrentTimestamp();
            String nonceStr = WXPayUtil.generateNonceStr();
            view.addObject("package", "prepay_id=" + wxPrePayId);
            view.addObject("appId", weiXinPayConfig.getAppid());
            view.addObject("timeStamp", currentTimestamp);
            view.addObject("nonceStr", nonceStr);
            Map<String, String> params = new HashMap<String, String>();
            params.put("appId", weiXinPayConfig.getAppid());
            params.put("timeStamp", currentTimestamp + "");
            params.put("nonceStr", nonceStr);
            params.put("package", "prepay_id=" + wxPrePayId);
            params.put("signType", "MD5");
            view.addObject("sign", WXPayUtil.generateSignature(params, weiXinPayConfig.getKey()));
        } else {
            //电脑端，生成二维码
            view = baseView(request, "微信支付", "pc/pay/weixinnative");
            view.addObject("code_url", wxPrePayId);
        }
        view.addObject("paymenOrders", bcPaymenordersResult);
        return view;
    }


    //支付回调
    @SneakyThrows
    private String getWxPrePayId(HttpServletRequest request, BcPaymenorders bcPaymenorders, String payType) {
//        https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
//        调起支付页面
        WXPayConfigImpl wxPayConfig = new WXPayConfigImpl(weiXinPayConfig);
        WXPay wxpay = new WXPay(wxPayConfig, true, true);
        Map<String, String> data = new HashMap<String, String>();
        data.put("body", bcPaymenorders.getItemName());
        data.put("out_trade_no", bcPaymenorders.getOrderId());
        data.put("fee_type", "CNY");
        //TODO 这里的金额先写固定，101，正式的时候要切换回来
        data.put("total_fee", "101");
//        data.put("total_fee", Convert.toInt(NumberUtil.mul(bcPaymenorders.getPayAmount(),
//                Convert.toBigDecimal(100))).toString());
        data.put("spbill_create_ip", IpUtils.getIpAddr(request));
        data.put("notify_url", weiXinPayConfig.getNotifyUrl() + "pay/weixin/notify");
        //手机端用JSAPI,电脑端用Native
        data.put("trade_type", payType);  // 此处指定为扫码支付
        data.put("product_id", bcPaymenorders.getId().toString());
        try {
            Map<String, String> resp = wxpay.unifiedOrder(data);
            if (payType.equals(WxPayEnum.JSAPI.getTitle())) {
                return resp.get("prepay_id");
            } else if (payType.equals(WxPayEnum.NATIVE.getTitle())) {
                return resp.get("code_url");
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信支付回调
     **/
    @SneakyThrows
    @PostMapping("notify")
    public String weixinNotify(HttpServletRequest request, HttpServletResponse response) {
        BufferedReader reader = request.getReader();
        String line = "";
        StringBuffer inputString = new StringBuffer();
        while ((line = reader.readLine()) != null) {
            inputString.append(line);
        }
        String notifyData = inputString.toString();
        request.getReader().close();
        System.out.println("----接收到的数据如下：---" + notifyData);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        WXPayConfigImpl wxPayConfig = new WXPayConfigImpl(weiXinPayConfig);
        WXPay wxpay = new WXPay(wxPayConfig, true, true);
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
            String result_code = notifyMap.get("result_code");
            String out_trade_no = notifyMap.get("out_trade_no");
            String returnCode = notifyMap.get("return_code");
            //回调支付ID
            String transactionId=notifyMap.get("transaction_id");
            if (returnCode.equals("SUCCESS")) {
                //修改订单状态
               bcPaymenordersService.createNotifyOrder(out_trade_no,transactionId);
                return returnXML(result_code);
            }
        }
        // 签名错误，如果数据里没有sign字段，也认为是签名错误
        return returnXML("FAIL");
    }


    private String returnXML(String return_code) {
        return "<xml><return_code><![CDATA["
                + return_code
                + "]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }
}
